{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Deep Net in Keras with TensorBoard"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this notebook, we adapt our [deep net](https://github.com/the-deep-learners/deep-learning-illustrated/blob/master/notebooks/deep_net_in_keras.ipynb) code to enable TensorBoard logging. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/the-deep-learners/deep-learning-illustrated/blob/master/notebooks/deep_net_in_keras_with_tensorboard.ipynb)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Load dependencies"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n"
     ]
    }
   ],
   "source": [
    "import keras\n",
    "from keras.datasets import mnist\n",
    "from keras.models import Sequential\n",
    "from keras.layers import Dense\n",
    "from keras.layers import Dropout \n",
    "from keras.layers.normalization import BatchNormalization \n",
    "from keras.optimizers import SGD\n",
    "from keras.callbacks import TensorBoard # new! "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Load data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "(X_train, y_train), (X_valid, y_valid) = mnist.load_data()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Preprocess data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train = X_train.reshape(60000, 784).astype('float32')\n",
    "X_valid = X_valid.reshape(10000, 784).astype('float32')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train /= 255\n",
    "X_valid /= 255"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "n_classes = 10\n",
    "y_train = keras.utils.to_categorical(y_train, n_classes)\n",
    "y_valid = keras.utils.to_categorical(y_valid, n_classes)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Design neural network architecture"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = Sequential()\n",
    "\n",
    "model.add(Dense(64, activation='relu', input_shape=(784,)))\n",
    "model.add(BatchNormalization())\n",
    "\n",
    "model.add(Dense(64, activation='relu'))\n",
    "model.add(BatchNormalization())\n",
    "\n",
    "model.add(Dense(64, activation='relu'))\n",
    "model.add(BatchNormalization())\n",
    "model.add(Dropout(0.2))\n",
    "\n",
    "model.add(Dense(10, activation='softmax'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "dense_1 (Dense)              (None, 64)                50240     \n",
      "_________________________________________________________________\n",
      "batch_normalization_1 (Batch (None, 64)                256       \n",
      "_________________________________________________________________\n",
      "dense_2 (Dense)              (None, 64)                4160      \n",
      "_________________________________________________________________\n",
      "batch_normalization_2 (Batch (None, 64)                256       \n",
      "_________________________________________________________________\n",
      "dense_3 (Dense)              (None, 64)                4160      \n",
      "_________________________________________________________________\n",
      "batch_normalization_3 (Batch (None, 64)                256       \n",
      "_________________________________________________________________\n",
      "dropout_1 (Dropout)          (None, 64)                0         \n",
      "_________________________________________________________________\n",
      "dense_4 (Dense)              (None, 10)                650       \n",
      "=================================================================\n",
      "Total params: 59,978\n",
      "Trainable params: 59,594\n",
      "Non-trainable params: 384\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "model.summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Configure model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Set TensorBoard logging directory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "tensorboard = TensorBoard('logs/deep-net')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Train!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 60000 samples, validate on 10000 samples\n",
      "Epoch 1/20\n",
      "60000/60000 [==============================] - 2s 31us/step - loss: 0.3810 - acc: 0.8874 - val_loss: 0.1646 - val_acc: 0.9467\n",
      "Epoch 2/20\n",
      "60000/60000 [==============================] - 1s 21us/step - loss: 0.1581 - acc: 0.9534 - val_loss: 0.1319 - val_acc: 0.9610\n",
      "Epoch 3/20\n",
      "60000/60000 [==============================] - 1s 21us/step - loss: 0.1173 - acc: 0.9642 - val_loss: 0.1138 - val_acc: 0.9661\n",
      "Epoch 4/20\n",
      "60000/60000 [==============================] - 1s 21us/step - loss: 0.0956 - acc: 0.9708 - val_loss: 0.1054 - val_acc: 0.9687\n",
      "Epoch 5/20\n",
      "60000/60000 [==============================] - 1s 22us/step - loss: 0.0791 - acc: 0.9750 - val_loss: 0.0931 - val_acc: 0.9712\n",
      "Epoch 6/20\n",
      "60000/60000 [==============================] - 1s 23us/step - loss: 0.0702 - acc: 0.9784 - val_loss: 0.0909 - val_acc: 0.9721\n",
      "Epoch 7/20\n",
      "60000/60000 [==============================] - 1s 22us/step - loss: 0.0645 - acc: 0.9790 - val_loss: 0.0831 - val_acc: 0.9745\n",
      "Epoch 8/20\n",
      "60000/60000 [==============================] - 1s 24us/step - loss: 0.0543 - acc: 0.9827 - val_loss: 0.0912 - val_acc: 0.9736\n",
      "Epoch 9/20\n",
      "60000/60000 [==============================] - 1s 22us/step - loss: 0.0498 - acc: 0.9836 - val_loss: 0.0907 - val_acc: 0.9731\n",
      "Epoch 10/20\n",
      "60000/60000 [==============================] - 1s 21us/step - loss: 0.0442 - acc: 0.9857 - val_loss: 0.0939 - val_acc: 0.9738\n",
      "Epoch 11/20\n",
      "60000/60000 [==============================] - 1s 22us/step - loss: 0.0411 - acc: 0.9866 - val_loss: 0.0959 - val_acc: 0.9727\n",
      "Epoch 12/20\n",
      "60000/60000 [==============================] - 1s 21us/step - loss: 0.0383 - acc: 0.9874 - val_loss: 0.0906 - val_acc: 0.9764\n",
      "Epoch 13/20\n",
      "60000/60000 [==============================] - 1s 22us/step - loss: 0.0363 - acc: 0.9879 - val_loss: 0.0865 - val_acc: 0.9756\n",
      "Epoch 14/20\n",
      "60000/60000 [==============================] - 1s 21us/step - loss: 0.0330 - acc: 0.9895 - val_loss: 0.0986 - val_acc: 0.9743\n",
      "Epoch 15/20\n",
      "60000/60000 [==============================] - 1s 21us/step - loss: 0.0300 - acc: 0.9900 - val_loss: 0.0883 - val_acc: 0.9761\n",
      "Epoch 16/20\n",
      "60000/60000 [==============================] - 1s 22us/step - loss: 0.0276 - acc: 0.9906 - val_loss: 0.0911 - val_acc: 0.9779\n",
      "Epoch 17/20\n",
      "60000/60000 [==============================] - 1s 23us/step - loss: 0.0270 - acc: 0.9908 - val_loss: 0.0937 - val_acc: 0.9751\n",
      "Epoch 18/20\n",
      "60000/60000 [==============================] - 1s 22us/step - loss: 0.0270 - acc: 0.9911 - val_loss: 0.0968 - val_acc: 0.9739\n",
      "Epoch 19/20\n",
      "60000/60000 [==============================] - 1s 21us/step - loss: 0.0240 - acc: 0.9919 - val_loss: 0.0947 - val_acc: 0.9747\n",
      "Epoch 20/20\n",
      "60000/60000 [==============================] - 1s 22us/step - loss: 0.0246 - acc: 0.9915 - val_loss: 0.0944 - val_acc: 0.9755\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<keras.callbacks.History at 0x7f3a54b2cf60>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.fit(X_train, y_train, \n",
    "          batch_size=128, \n",
    "          epochs=20, verbose=1, \n",
    "          validation_data=(X_valid, y_valid),\n",
    "          callbacks=[tensorboard])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
